<?php


namespace addon\hotel\model;

use addon\hotel\model\HotelMember as HotelMemberModel;
use addon\hotel\model\OrderCommon as OrderCommonModel;
use app\model\BaseModel;
use app\model\goods\GoodsStock;
use app\model\hotel\Baoyu;
use app\model\hotel\Hotel;
use app\model\member\Member;
use app\model\member\MemberAccount;
use app\model\order\Config;
use app\model\system\Cron;
use app\model\system\Pay;
use think\Db;

class OrderCreate extends BaseModel
{

    public $order_money = 0;//订单金额
    public $room_money = 0;//房间金额
    public $pay_money = 0;//支付总价
    public $room_num = 0;  //房间数量
    public $order_name = '';  //订单详情
    public $error = 0;  //是否有错误
    public $error_msg = '';  //错误描述
    public $pay_type = 'ONLINE_PAY';

    public $member_balance_money = 0;//会员账户余额(计算过程中会逐次减少)
    public $balance_money = 0;

    /**
     * 订单创建
     * @param $data
     * @return array|mixed
     */
    public function create($data)
    {
        $calculate_data = $this->calculate($data);

        if (isset($calculate_data['code']) && $calculate_data['code'] < 0)
            return $calculate_data;

        if ($this->error > 0) {
            return $this->error(['error_code' => $this->error], $this->error_msg);
        }
        $calculate_data = $calculate_data['data'];
        $pay = new Pay();

        $out_trade_no = $pay->createOutTradeNo($data['member_id']);

        model("hotel_order")->startTrans();

        $order_name = $calculate_data['order_name'];

        $order_common = new OrderCommon();
        try {
            $order_no = $this->createOrderNo($data['member_id']);

            $data_order = [
                'order_no' => $order_no,
                'member_id' => $data['member_id'],
                'room_id' => $data['room_id'],
                'hotel_id' => $calculate_data['room_info']['hotel_id'],
                'hotel_name' => $calculate_data['hotel_info']['hotel_name'],
                'room_money' => $calculate_data['room_money'],
                'real_room_money' => $calculate_data['real_room_money'],
                'room_price' => $calculate_data['room_info']['price'],
                'room_name' => $calculate_data['room_info']['room_name'],
                'room_image' => $calculate_data['room_image'],
                'room_num' => $data['room_num'],
                'arrival_time' => $data['arrival_time'],
                'mobile' => $data['mobile'],
                'realname' => $data['realname'],
                'start_date' => $data['start_date'],
                'end_date' => $data['end_date'],
                'create_time' => time(),
                'baoyu_room_id' => $calculate_data['baoyu_room_id'] ?? 0,
                'order_money' => $calculate_data['order_money'],
                'balance_money' => $calculate_data['balance_money'],
                'pay_money' => $calculate_data['pay_money'],
                'point_money' => $calculate_data['point_money'] ?? 0,
                'discount_money' => $calculate_data['discount_money'],
                'day' => $calculate_data['day'],
                'use_point' => $calculate_data[ 'max_usable_point' ] ?? 0,
                'order_name' => $order_name,
                'out_trade_no'=>$out_trade_no,
                'order_status_name' => '待支付',
                'order_status_action'=>json_encode($order_common->order_status[0], JSON_UNESCAPED_UNICODE)
            ];

            $date = [];

            for($i=0;$i<$calculate_data['day'];$i++){

                $begin = date_to_time($data['start_date'])+$i*86400;
                $end = date_to_time($data['start_date'])+$i*86400+86399;
                $day = date('Y-m-d',$begin);

                $order_count = \think\facade\Db::name('hotel_order')
                    ->where('room_id', $data['room_id'])
                    //->where('pay_status', 1)
                    ->where('order_status', '>',0)
                    ->where('start_date_timestamp', '<=',$begin)
                    ->where('end_date_timestamp', '>=',$end)
                    ->sum('room_num');
                //dump($order_count);
                if ($order_count>=$calculate_data['room_info']['stock']){
                    array_push($date,$day);
                    //model("hotel_order")->rollback();
                    //return $this->error('',$day.'日期库存不足');
                }
            }

            if (count($date)>0){
                model("hotel_order")->rollback();
                return $this->error('',implode(',',$date).'日期库存不足');
            }

            $order_id = model("hotel_order")->add($data_order);

            //自营请求第三方订单提交接口
            /*if ($calculate_data['hotel_info']['direct']==1){
                $baoyu_model = new Baoyu();
                //是否可预定
                //$baoyu_model->canSchedule($calculate_data['room_info']['baoyu_id'],$data['start_date'],$data['end_date']);

                //创建订单
                $baoyu_data = [
                    'channel'=>$calculate_data['hotel_info']['hotel_name'],//订单显示来源的自定义名称
                    'channelOrderId'=>$order_id,//外部订单id
                    'roomId'=>$data_order['baoyu_room_id'],
                    'checkIn'=>$data['start_date'],//入住时间
                    'checkOut'=>$data['end_date'],//退房时间
                    'renterName'=>$data['realname'],//租客姓名
                    'renterPhone'=>$data['mobile'],//租客手机
                    //'renterRemark'=>'',//备注
                    'price'=>$data_order['pay_money'],//订单金额，单位元
                    //'unitName'=>'',//订单对应的民宿侧房源名称
                    //'channelUnitId'=>'',//订单对应的民宿侧房源id，此项仅供民宿侧自用
                ];
                //dump($baoyu_data);
                $res = $baoyu_model->createOrder($baoyu_data);

                if ($res['data']['state']!=0){
                    return $this->error('', '宝寓订单创建失败');
                }
                $baoyu_order_id = $res['data']['data']['contract']['id'];
                model("hotel_order")->update(['baoyu_order_id'=>$baoyu_order_id],[['order_id','=',$order_id]]);
            }*/

            /*$goods_stock_model = new RoomStock();
            $stock_result = $goods_stock_model->decStock(["room_id" => $data['room_id'], "room_num" => $data['room_num']]);
            if ($stock_result["code"] != 0) {
                model("hotel_order")->rollback();
                return $stock_result;
            }*/
            // 扣除抵现积分
            if ($calculate_data[ 'is_point' ] && $calculate_data[ 'max_usable_point' ] > 0) {
                $member_account_model = new MemberAccount();
                $point_result = $member_account_model->addMemberAccount($calculate_data[ 'member_id' ], 'point', -$calculate_data[ 'max_usable_point' ], 'pointcash', $order_id, "积分抵现扣除积分");
                if ($point_result[ "code" ] < 0) {
                    model("hotel_order")->rollback();
                    return $point_result;
                }
            }

            //扣除余额(统一扣除)
            if ($calculate_data["balance_money"] > 0) {
                $balance_result = $this->useBalance($calculate_data);
                if ($balance_result["code"] < 0) {
                    model("hotel_order")->rollback();
                    return $balance_result;
                }
            }
            $this->addOrderCronClose($order_id);//增加关闭订单自动事件
           /* $inc_stock_time = strtotime($data['end_date'].' 12:00');
            //到离店日期 加上库存
            $cron_model = new Cron();
            $cron_model->addCron(1, 0, "酒店订单自动释放库存", "CronHotelRoomIncStock", $inc_stock_time, $order_id);*/

            /*$res = event("HotelOrderCreate", ['order_id' => $order_id]);

            dump($res);
            dump(444);die;*/
            //酒店添加用户
            $order_model = new OrderCommonModel();
            $order_info = $order_model->getOrderInfo([ [ 'order_id', '=', $order_id ] ], 'hotel_id,member_id');
            $order_info = $order_info['data'];
            if (!empty($order_info)) {
                //添加店铺关注记录
                $shop_member_model = new HotelMemberModel();
                $res = $shop_member_model->addHotelMember($order_info['hotel_id'], $order_info['member_id'], 0);
                //return $res;
            }

            $order_name_title = $order_name;
            $pay->addPay(0, $out_trade_no, $this->pay_type, $order_name_title, $order_name_title, $data_order['pay_money'], '', 'HotelOrderPayNotify', '');

            model("hotel_order")->commit();
            return $this->success($out_trade_no);
        } catch ( \Exception $e ) {
            model("hotel_order")->rollback();
            return $this->error('', $e->getMessage() . $e->getFile() . $e->getLine());
        }

    }


    public function calculate($data)
    {
        $data = $this->initMemberAccount($data);//初始化会员账户
        //余额付款
        if ($data['is_balance'] > 0) {
            $this->member_balance_money = $data["member_account"]["balance_total"] ?? 0;
        }
        // 积分抵现
        $data[ 'max_usable_point' ] = 0;

        //房间信息
        $room_model = new Room();

        $room_info = $room_model->getRoomInfo($data['room_id']);
        $room_info = $room_info['data'];
        /*if ($data['room_num']>$room_info['stock']){
            $this->error = 1;
            $this->error_msg = "{$room_info['room_name']}”库存不足";
            return $this->error(['error_code' => 1], "{$room_info['room_name']}”库存不足");
        }*/
        // 是否参与会员等级折扣
        $price_result = $room_model->getRoomPrice($room_info['room_id'], $data['member_id']);
        $price_info = $price_result[ "data" ];
        $price = $price_info[ "price" ];
        $room_info['member_price'] = $price;
        $room_type = model('hotel_room_type')->getInfo(['baoyu_type_id'=>$room_info['type_id']]);
        $room_info['room_type_info'] = $room_type;
        $data['room_info'] = $room_info;

        //酒店信息
        $hotel_model = new Hotel();

        $hotel_info = $hotel_model->getHotelInfo([['hotel_id','=',$room_info['hotel_id']]],'hotel_id,hotel_name,status,direct');

        $hotel_info = $hotel_info['data'];

        $data['hotel_info'] = $hotel_info;

        if (!$hotel_info['status']){
            $this->error = 1;
            $this->error_msg = "酒店“{$hotel_info['hotel_name']}”已停业";
            return $this->error(['error_code' => 1], "酒店“{$hotel_info['hotel_name']}”已停业");
        }

        /*if ($room_info['stock']==0||$data['room_num']>$room_info['stock']){
            $this->error = 1;
            $this->error_msg = "房间“{$room_info['room_name']}”库存不足";
            return $this->error(['error_code' => 1], "房间“{$room_info['room_name']}”库存不足");
        }*/

        //自营请求第三方订单提交接口
        if ($hotel_info['direct']==1){
            /*if ($data['room_num']>explode(',',$room_info['baoyu_id'])){
                $this->error = 1;
                $this->error_msg = "房间“{$room_info['room_name']}”库存不足";
                return $this->error(['error_code' => 1], "房间“{$room_info['room_name']}”库存不足");
            }*/
            $baoyu_model = new Baoyu();

            //是否可预定
            $res = $baoyu_model->canScheduleBatch($room_info['baoyu_id'],$data['start_date'],$data['end_date']);

            if ($res['data']['state']==0){
                $baoyu_data = $res['data']['data']['id2bookable'];

                if (checkAllFalse($baoyu_data)){
                    $this->error = 1;
                    $this->error_msg = "房间“{$room_info['room_name']}”不可预定";
                    return $this->error(['error_code' => 1], "房间“{$room_info['room_name']}”不可预定");
                }

                $baoyu_room_list = [];
                foreach ($baoyu_data as $k=>$v){
                    if ($v==true){
                        array_push($baoyu_room_list,$k);
                    }
                }
                if ($data['room_num']>count($baoyu_room_list)){
                    $this->error = 1;
                    $this->error_msg = "房间“{$room_info['room_name']}”库存不足";
                    return $this->error(['error_code' => 1], "房间“{$room_info['room_name']}”库存不足");
                }

                $numToExtract = $data['room_num'];
                $randomKeys = array_rand($baoyu_room_list, $numToExtract);

                // 确保 $randomKeys 是数组（当抽取多个元素时）
                if (!is_array($randomKeys)) {
                    $randomKeys = [$randomKeys];
                }

                $extractedArray = [];
                foreach ($randomKeys as $key) {
                    $extractedArray[] = $baoyu_room_list[$key];
                }

                $data['baoyu_room_id'] = implode(',',$extractedArray);

            }

        }

        $day = daysBetweenDates($data['start_date'],$data['end_date']);

        $data['day'] = $day;

        $room_money = bcmul($data['room_num'],$room_info['price'],2);

        $real_room_money = bcmul($data['room_num'],$price,2);

        $order_money = bcmul($day,$real_room_money,2);

        $point = $data[ 'member_account' ][ 'point' ];

        $point_money = 0;
        if ($data[ 'is_point' ] && $point > 0) {

            $point_money = $point;
            $data[ 'max_usable_point' ] = $point;
            if ($point_money > $order_money) {
                $point_money = $order_money;
            }

            //$order_money-=$point_money;
            $data[ 'point_money' ] = $point_money;
            $real_room_money-=$point_money;
        }

        //余额抵扣(判断是否使用余额)
        if ($this->member_balance_money > 0) {
            if ($order_money <= $this->member_balance_money) {
                $balance_money = $order_money;
            } else {
                $this->error = 1;
                $this->error_msg = "余额不足";
                return $this->error(['error_code' => 1], "余额不足");
                //$balance_money = $this->member_balance_money;
            }
        } else {
            $balance_money = 0;
        }
        $pay_money = $order_money - $balance_money - $point_money;//计算出实际支付金额

        $data['room_image'] = explode(',',$room_info['images'])[0];
        $data['order_name'] = $hotel_info['hotel_name'].','.$room_info['room_name'].','.$data['room_num'].'间';
        $data['room_money'] = $room_money;
        $data['real_room_money'] = $real_room_money;
        $data['order_money'] = $order_money;
        $data['pay_money'] =  $pay_money;
        $data['balance_money'] = $balance_money;
        $data['discount_money'] = 0;
        return $this->success($data);
    }

    /**
     * 增加订单自动关闭事件
     * @param $order_id
     */
    public function addOrderCronClose($order_id)
    {
        //计算订单自动关闭时间
        $config_model = new Config();
        $order_config_result = $config_model->getOrderEventTimeConfig();
        $order_config = $order_config_result["data"];
        $now_time = time();
        if (!empty($order_config)) {
            $execute_time = $now_time + $order_config["value"]["auto_close"] * 60;//自动关闭时间
        } else {
            $execute_time = $now_time + 3600;//尚未配置  默认一天
        }
        $cron_model = new Cron();
        $cron_model->addCron(1, 0, "订单自动关闭", "CronHotelOrderClose", $execute_time, $order_id);
    }


    /**
     * 初始化会员账户
     * @param $data
     * @return mixed
     */
    public function initMemberAccount($data)
    {
        $member_model = new Member();
        $member_info_result = $member_model->getMemberDetail($data["member_id"]);
        $member_info = $member_info_result["data"];

        if (!empty($member_info)) {
            if (!empty($member_info["pay_password"])) {
                $is_pay_password = 1;
            } else {
                $is_pay_password = 0;
            }
            unset($member_info["pay_password"]);
            $member_info["is_pay_password"] = $is_pay_password;
            $data['member_account'] = $member_info;
        }

        return $data;
    }

    /**
     * 使用余额
     * @param $order_data
     * @return array
     */
    public function useBalance($data, $self = null)
    {
        $self = $self ?? $this;
        $self->pay_type = "BALANCE";
        $member_model = new Member();

        $balance_money = $data["member_account"]["balance_money"];//不可提现余额

        $member_account_model = new MemberAccount();
        $surplus_banance = $data["balance_money"];
        //优先扣除不可提现余额

        if ($surplus_banance > 0) {
            $result = $member_account_model->addMemberAccount($data["member_id"], "balance_money", -$surplus_banance, "order", "余额付款", "订单余额付款,扣除余额:" . $surplus_banance);
        }

        return $result;

    }

    /**
     * 生成订单编号
     *
     * @param array $site_id
     */
    public function createOrderNo($member_id)
    {

        $order_no = createno('create_order_no','', $member_id);
        return $order_no;
    }
}